/**
*   @file    Mcu.c
*   @implements Mcu.c_Artifact
*   @version 1.0.1
*
*   @brief   AUTOSAR Mcu - Implementation of external interface.
*   @details High level validation of the data managed to/from high level.
*
*   @addtogroup MCU
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.3 MCAL
*   Platform             : ARM
*   Peripheral           : MC
*   Dependencies         : none
*
*   Autosar Version      : 4.3.1
*   Autosar Revision     : ASR_REL_4_3_REV_0001
*   Autosar Conf.Variant :
*   SW Version           : 1.0.1
*   Build Version        : S32K14x_MCAL_1_0_1_RTM_ASR_REL_4_3_REV_0001_20190621
*
*   (c) Copyright 2006-2016 Freescale Semiconductor, Inc. 
*       Copyright 2017-2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/


#ifdef __cplusplus
extern "C"{
#endif

/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "Mcal.h"
#include "Mcu.h"
#include "Mcu_IPW.h"

/*==================================================================================================
                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/
/**
* @brief  This enumerated type contains the Mcu driver's possible states.
*/
typedef enum
{
    MCU_UNINIT = 0x3U,  /**< @brief The Mcu driver is not uninitialized. */
    MCU_IDLE = 0xCU,  /**< @brief = 0xE1 The Mcu driver is currently idle. */
    MCU_BUSY = 0xAU   /**< @brief = 0xD2 The Mcu driver is currently busy. */
} Mcu_StatusType;


/*==================================================================================================
                                       LOCAL VARIABLES
==================================================================================================*/
static VAR(uint8, MCU_VAR) Mcu_au8ClockConfigIds[MCU_MAX_CLKCONFIGS];	/* Array for saving the Clock configuration Ids. */
static VAR(uint8, MCU_VAR) Mcu_au8ModeConfigIds[MCU_MAX_MODECONFIGS];	/* Array for saving the Mode configuration Ids. */
P2CONST( Mcu_ConfigType, MCU_VAR, MCU_APPL_CONST) Mcu_pConfigPtr = NULL_PTR;

/*==================================================================================================
                                       GLOBAL CONSTANTS
==================================================================================================*/
extern CONST(Mcu_ConfigType, MCU_CONST) Mcu_PBCfgVariantPredefined;


/*==================================================================================================
                                       GLOBAL FUNCTIONS
==================================================================================================*/

/**
* @brief            MCU driver initialization function.
* @details          This routine initializes the MCU Driver.
*                   The intention of this function is to make the configuration setting for power
*                   down, clock and Ram sections visible within the MCU Driver.
*
* @param[in]        pConfigPtr   Pointer to configuration structure.
*
* @return           void
*
* @api
*
* @implements Mcu_Init_Activity
*
*/
FUNC(void, MCU_CODE) Mcu_Init( P2CONST( Mcu_ConfigType, AUTOMATIC, MCU_APPL_CONST) pConfigPtr)
{
    /* Temporary variable for looping all the configurations. */
    VAR(uint32, AUTOMATIC) u32NoConfigs;

    /* Get a local copy of the driver initialization structure. */
    Mcu_pConfigPtr = &Mcu_PBCfgVariantPredefined;
    MCU_PARAM_UNUSED(pConfigPtr);

    /* When Post-Build is used the input parameter 'pConfigPtr' is mandatory to be different than

    /* Save the Mcu Mode IDs configurations. */
    for(u32NoConfigs = (uint32)0U; u32NoConfigs < Mcu_pConfigPtr->Mcu_NoModeConfigs; u32NoConfigs++)
    {
    	//used by Mcu_SetMode()
        Mcu_au8ModeConfigIds[(*Mcu_pConfigPtr->Mcu_apModeConfig)[u32NoConfigs].Mcu_ModeConfigId] = (uint8)u32NoConfigs;
    }

    /* Save the Mcu Clock IDs configurations. */
    for(u32NoConfigs = (uint32)0U; u32NoConfigs < Mcu_pConfigPtr->Mcu_NoClkConfigs; u32NoConfigs++)
    {
    	//used by Mcu_InitClock()
        Mcu_au8ClockConfigIds[(*Mcu_pConfigPtr->Mcu_apClockConfig)[u32NoConfigs].Mcu_ClkConfigId] = (uint8)u32NoConfigs;
    }

    Mcu_Ipw_Init( Mcu_pConfigPtr->Mcu_pHwIPsConfig);
    /* the driver was initialized, set the proper status */
}


/**
* @brief            MCU driver clock initialization function.
* @details          This function initializes the PLL and MCU specific clock options. The clock
*                       setting is provided from the configuration structure.
*
* @param[in]        ClockSetting   Clock setting ID from config structure to be used.
*
* @return           Command has or has not been accepted.
* @retval           E_OK        The driver state allowed the execution of the function and the
*                                   provided parameter was in range
* @retval           E_NOT_OK    The driver state did not allowed execution or the parameter was
*                                   invalid
*
* @api
*
* @implements Mcu_InitClock_Activity
*
*/
FUNC( Std_ReturnType, MCU_CODE) Mcu_InitClock( VAR( Mcu_ClockType, AUTOMATIC) ClockSetting)
{
    /* Return the success of the clock initialization operation. */
    VAR(Std_ReturnType, AUTOMATIC) ClockStatus;

	/* Check if Clock configuration is valid. */
	Mcu_Ipw_InitClock(&(*Mcu_pConfigPtr->Mcu_apClockConfig)[Mcu_au8ClockConfigIds[ClockSetting]]);
	/* Command has been accepted. */
	ClockStatus = (Std_ReturnType)E_OK;

    return (Std_ReturnType)ClockStatus;
}


/**
* @brief            This function sets the MCU power mode.
* @details          This function activates MCU power mode from config structure selected by McuMode
*                       parameter.
*                   If the driver state is invalid or McuMode is not in range the function will skip
*                       changing the mcu mode.
*
* @param[in]        McuMode   MCU mode setting ID from config structure to be set.
*
* @return           void
*
* @api
*
* @implements Mcu_SetMode_Activity
*
*/
FUNC(void, MCU_CODE) Mcu_SetMode(VAR(Mcu_ModeType, AUTOMATIC) McuMode)
{
	Mcu_Ipw_SetMode( &(*Mcu_pConfigPtr->Mcu_apModeConfig)[Mcu_au8ModeConfigIds[McuMode]] );
}


#if (MCU_INIT_CLOCK == STD_ON)
#if (MCU_NO_PLL == STD_OFF)
/**
* @brief            This function activates the PLL clock to the MCU clock distribution.
* @details          Function completes the PLL configuration and then activates the PLL clock to
*                       MCU. If the MCU_NO_PLL is TRUE the Mcu_DistributePllClock has to be
*                       disabled.
*                   The function will not distribute the PLL clock if the driver state does not
*                       allow it, or the PLL is not stable.
*
* @return           Std_ReturnType
* @retval           E_OK        Command has been accepted.
* @retval           E_NOT_OK    Command has not been accepted.
*
* @api
*
* @implements Mcu_DistributePllClock_Activity
*
*/
FUNC( Std_ReturnType, MCU_CODE) Mcu_DistributePllClock(VAR( void, AUTOMATIC))
{
    /* Return variable */
    VAR(Std_ReturnType, AUTOMATIC) PllStatus = (Std_ReturnType)E_NOT_OK;

	/* Set the PLL as System Clock if it is locked and enabled by the current mode.
	If the PLL0 is already selected as system clock, then this function will return without
	doing anything. */
	Mcu_Ipw_DistributePllClock();

	return (Std_ReturnType)PllStatus;
}
#endif /* (MCU_NO_PLL == STD_OFF) */
#endif /* (MCU_INIT_CLOCK == STD_ON) */


/**
* @brief            This function returns the lock status of the PLL.
* @details          The user takes care that the PLL is locked by executing Mcu_GetPllStatus.
*                       If the MCU_NO_PLL is TRUE the MCU_GetPllStatus has to return
*                       MCU_PLL_STATUS_UNDEFINED.
*                   It will also return MCU_PLL_STATUS_UNDEFINED if the driver state was invalid
*
* @return           Provides the lock status of the PLL.
* @retval           MCU_PLL_STATUS_UNDEFINED    PLL Status is unknown.
* @retval           MCU_PLL_LOCKED              PLL is locked.
* @retval           MCU_PLL_UNLOCKED            PLL is unlocked.
*
* @api
*
* @implements Mcu_GetPllStatus_Activity
*
*
*/
FUNC( Mcu_PllStatusType, MCU_CODE) Mcu_GetPllStatus( VAR( void, AUTOMATIC))
{
    /* Return variable */
    VAR(Mcu_PllStatusType, AUTOMATIC) ePllStatus;

	/* Get status of the PLL (if enabled in current mode).
	At this point the return value can be only MCU_PLL_LOCKED or MCU_PLL_UNLOCKED. */
	ePllStatus = Mcu_Ipw_GetPllStatus();

    return (Mcu_PllStatusType)ePllStatus;
}


/**
* @brief            This function returns the Reset reason.
* @details          This routine returns the Reset reason that is read from the hardware.
*
*
* @return           Reason of the Reset event.
* @retval           MCU_POR_RESET           Power on event.
* @retval           MCU_SOFT_DEST_RESET     Software destructive reset.
* @retval           MCU_FFRR_RESET          FCCU failure to react reset.
* @retval           MCU_EDR_RESET           Functional reset escalation.
* @retval           MCU_TSR_DEST_RESET      Temperature sensor destructive reset.
* @retval           MCU_VOR_DEST_RESET      Voltage out of range destructive reset.
* @retval           MCU_EXR_RESET           External reset event.
* @retval           MCU_ST_DONE_RESET       Self-test completed event.
* @retval           MCU_SOFT_FUNC_RESET     Software destructive event.
* @retval           MCU_FCCU_HARD_RESET     FCCU hard reaction request event.
* @retval           MCU_FCCU_SOFT_RESET     FCCU soft reaction request event.
* @retval           MCU_JTAG_RESET          JTAG initiated reset event.
* @retval           MCU_TSR_FUNC_RESET      Temperature sensor functional reset.
* @retval           MCU_VOR_FUNC_RESET      Voltage out of range functional reset.
*
* @api
*
* @implements Mcu_GetResetReason_Activity
*
*
*/
FUNC(Mcu_ResetType, MCU_CODE) Mcu_GetResetReason(VAR( void, AUTOMATIC))
{
    /* Return value of the function. */
    VAR(Mcu_ResetType, AUTOMATIC) eResetReason;

    /* Get the reset reason. */
    eResetReason = (Mcu_ResetType)Mcu_Ipw_GetResetReason();

    return (Mcu_ResetType)eResetReason;
}


/**
* @brief            This function returns the Raw Reset value.
* @details          This routine returns the Raw Reset value that is read from the hardware.
*
* @return           Description of the returned value.
* @retval           uint32   Code of the Raw reset value.
*                   The bit order in the returned value is:
*                   [ 0] - MC_RGM_FES_F_EXR_MASK32
*                   [ 1] - MC_RGM_FES_F_ST_DONE_MASK32
*                   [ 2] - MC_RGM_FES_F_SOFT_FUNC_MASK32
*                   [ 3] - MC_RGM_FES_F_FCCU_HARD_MASK32
*                   [ 4] - MC_RGM_FES_F_FCCU_SOFT_MASK32
*                   [ 5] - MC_RGM_FES_F_JTAG_FUNC_MASK32
*                   [ 6] - MC_RGM_FES_F_TSR_FUNC_MASK32
*                   [ 7] - MC_RGM_FES_F_VOR_FUNC_MASK32
*                   [16] - MC_RGM_DES_F_POR_MASK32
*                   [17] - MC_RGM_DES_F_SOFT_DEST_MASK32
*                   [18] - MC_RGM_DES_F_FFRR_MASK32
*                   [19] - MC_RGM_DES_F_EDR_MASK32
*                   [20] - MC_RGM_DES_F_TSR_DEST_MASK32
*                   [21] - MC_RGM_DES_F_VOR_DEST_MASK32
*
* @api
*
* @implements Mcu_GetResetRawValue_Activity
*
*/
FUNC( Mcu_RawResetType, MCU_CODE) Mcu_GetResetRawValue( VAR( void, AUTOMATIC))
{
    /* Return value of the function. */
    VAR( Mcu_RawResetType, AUTOMATIC) RawResetValue;
	
    RawResetValue = (Mcu_RawResetType)Mcu_Ipw_GetResetRawValue();
	
    return (Mcu_RawResetType)RawResetValue;
}


/**
* @brief            This function performs a micro-controller reset.
* @details          This function performs a micro-controller reset by using the hardware feature of
*                   the micro-controller. In case the function returns, the user must reset the
*                   platform using an alternate reset mechanism
*
* @return           void
*
* @api
*
* @implements Mcu_PerformReset_Activity
*
*/
FUNC( void, MCU_CODE) Mcu_PerformReset( VAR( void, AUTOMATIC))
{
    Mcu_Ipw_PerformReset( Mcu_pConfigPtr->Mcu_pHwIPsConfig);
    /* we should not get here */
    /* it's the app. responsibility to detect if the reset failed */
}



#ifdef __cplusplus
}
#endif

/** @} */
